```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深入解析Java HashSet扩容机制</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
            background-color: #f9f9f9;
        }
        .hero {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 6rem 0;
            position: relative;
            overflow: hidden;
        }
        .hero::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            height: 40px;
            background: linear-gradient(to top, #f9f9f9, transparent);
        }
        .hero-title {
            font-family: 'Noto Serif SC', serif;
            font-weight: 700;
            text-shadow: 0 2px 4px rgba(0,0,0,0.2);
        }
        .hero-subtitle {
            font-weight: 300;
            opacity: 0.9;
        }
        .content-card {
            background: white;
            border-radius: 10px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.05);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        .content-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 30px rgba(0,0,0,0.1);
        }
        .section-title {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: #2d3748;
            position: relative;
            padding-left: 1.5rem;
        }
        .section-title::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0.4em;
            height: 1em;
            width: 5px;
            background: linear-gradient(to bottom, #667eea, #764ba2);
            border-radius: 3px;
        }
        .list-item {
            position: relative;
            padding-left: 2rem;
            margin-bottom: 0.75rem;
        }
        .list-item::before {
            content: '\f054';
            font-family: 'Font Awesome 6 Free';
            font-weight: 900;
            position: absolute;
            left: 0;
            color: #667eea;
            font-size: 0.8em;
        }
        .code-block {
            background: #2d3748;
            color: #e2e8f0;
            border-radius: 6px;
            padding: 1.25rem;
            font-family: monospace;
            overflow-x: auto;
        }
        .footer {
            background: #1a202c;
            color: #e2e8f0;
        }
        .footer a:hover {
            color: #a0aec0;
        }
        .highlight {
            background: linear-gradient(120deg, #f0abfc 0%, #f0abfc 100%);
            background-repeat: no-repeat;
            background-size: 100% 40%;
            background-position: 0 88%;
        }
        .mermaid {
            background: white;
            padding: 1.5rem;
            border-radius: 10px;
            margin: 2rem 0;
            box-shadow: 0 5px 15px rgba(0,0,0,0.05);
        }
        .image-zoom {
            transition: transform 0.3s ease;
            cursor: zoom-in;
        }
        .image-zoom:hover {
            transform: scale(1.03);
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero">
        <div class="container mx-auto px-6 text-center">
            <h1 class="hero-title text-4xl md:text-5xl lg:text-6xl mb-4">深入解析Java <span class="highlight">HashSet</span>扩容机制</h1>
            <p class="hero-subtitle text-xl md:text-2xl max-w-3xl mx-auto">从底层实现到性能优化，全面剖析Set集合的核心机制</p>
            <div class="mt-8 flex justify-center space-x-4">
                <a href="#content" class="px-6 py-3 bg-white text-indigo-700 rounded-full font-medium hover:bg-gray-100 transition duration-300">
                    <i class="fas fa-book-open mr-2"></i>开始阅读
                </a>
                <a href="#visualization" class="px-6 py-3 border border-white text-white rounded-full font-medium hover:bg-white hover:bg-opacity-10 transition duration-300">
                    <i class="fas fa-project-diagram mr-2"></i>可视化解析
                </a>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="container mx-auto px-6 py-12 max-w-5xl">
        <div class="grid grid-cols-1 gap-8">
            <!-- Introduction -->
            <div class="content-card p-8">
                <p class="text-lg text-gray-700 mb-6">
                    <span class="text-indigo-600 font-medium">Set</span> 是 Java 中的一个集合接口，<span class="text-indigo-600 font-medium">HashSet</span> 是其最常用的实现类。<span class="text-indigo-600 font-medium">HashSet</span> 的底层实现基于 <span class="text-indigo-600 font-medium">HashMap</span>，因此它的扩容机制与 <span class="text-indigo-600 font-medium">HashMap</span> 的扩容机制类似。
                </p>
                <div class="flex flex-wrap gap-4 mt-6">
                    <div class="bg-indigo-50 text-indigo-800 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-random mr-2"></i>无序存储
                    </div>
                    <div class="bg-indigo-50 text-indigo-800 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-ban mr-2"></i>元素唯一
                    </div>
                    <div class="bg-indigo-50 text-indigo-800 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-expand mr-2"></i>动态扩容
                    </div>
                    <div class="bg-indigo-50 text-indigo-800 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-bolt mr-2"></i>高性能
                    </div>
                </div>
            </div>

            <!-- Content Section 1 -->
            <div class="content-card p-8" id="content">
                <h2 class="section-title text-2xl mb-6">1. 扩容触发条件</h2>
                <div class="space-y-4">
                    <div class="list-item">
                        <span class="font-medium">负载因子:</span> <span class="text-indigo-600">HashSet</span> 的扩容机制与 <span class="text-indigo-600">HashMap</span> 的扩容机制密切相关。<span class="text-indigo-600">HashSet</span> 的默认负载因子为 0.75，这意味着当 <span class="text-indigo-600">HashSet</span> 的元素数量达到容量的 75% 时，会触发扩容。负载因子用于平衡空间和性能，避免过度扩容导致内存浪费，同时保持较低的冲突率。
                    </div>
                    <div class="list-item">
                        <span class="font-medium">容量:</span> 容量是 <span class="text-indigo-600">HashSet</span> 底层 <span class="text-indigo-600">HashMap</span> 中数组的长度。当 <span class="text-indigo-600">HashSet</span> 的大小（即元素数量）达到 <span class="font-mono bg-gray-100 px-1 rounded">容量 * 负载因子</span> 时，扩容操作会被触发。
                    </div>
                </div>
            </div>

            <!-- Content Section 2 -->
            <div class="content-card p-8">
                <h2 class="section-title text-2xl mb-6">2. 扩容过程</h2>
                <div class="space-y-4">
                    <div class="list-item">
                        <span class="font-medium">计算新容量:</span> 当触发扩容时，<span class="text-indigo-600">HashSet</span> 的底层 <span class="text-indigo-600">HashMap</span> 会将数组容量扩大为原容量的两倍。新的容量是根据原数组容量的两倍来决定的，以减少哈希冲突并提高性能。
                    </div>
                    <div class="list-item">
                        <span class="font-medium">重新哈希:</span> 扩容后，所有的键值对（在 <span class="text-indigo-600">HashSet</span> 中仅存储键）需要重新计算哈希值，并重新分配到新的数组桶中。这个过程称为重新哈希。新的桶数组会根据键的哈希值重新分配原有的元素，以维持良好的性能。
                    </div>
                    <div class="list-item">
                        <span class="font-medium">迁移元素:</span> 在扩容过程中，<span class="text-indigo-600">HashSet</span> 会遍历原有的桶数组，并将每个桶中的元素迁移到新的桶数组中。这涉及到重新计算哈希位置和可能的链表或红黑树的更新。
                    </div>
                </div>
                <div class="mt-8">
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1644807018404-28691fd6-5e06-4b5b-b108-7658e345e0ef.png" alt="HashSet扩容过程图示" class="w-full rounded-lg image-zoom">
                </div>
            </div>

            <!-- Content Section 3 -->
            <div class="content-card p-8">
                <h2 class="section-title text-2xl mb-6">3. 扩容的影响</h2>
                <div class="grid md:grid-cols-2 gap-6">
                    <div class="bg-indigo-50 p-6 rounded-lg">
                        <div class="flex items-center mb-3">
                            <i class="fas fa-tachometer-alt text-indigo-600 text-xl mr-3"></i>
                            <h3 class="font-semibold text-lg">性能影响</h3>
                        </div>
                        <p>扩容是一个 O(n) 的操作，因为所有的元素都需要重新哈希并迁移到新的数组中。尽管扩容会影响性能，但这种影响是局部的，通常在扩容完成后，<span class="text-indigo-600">HashSet</span> 的操作性能会得到显著提升。</p>
                    </div>
                    <div class="bg-indigo-50 p-6 rounded-lg">
                        <div class="flex items-center mb-3">
                            <i class="fas fa-memory text-indigo-600 text-xl mr-3"></i>
                            <h3 class="font-semibold text-lg">空间影响</h3>
                        </div>
                        <p>扩容增加了内存使用，因为新的数组需要更多的空间来存储元素。然而，合理的负载因子和扩容策略能够在性能和内存使用之间取得平衡。</p>
                    </div>
                </div>
            </div>

            <!-- Content Section 4 -->
            <div class="content-card p-8">
                <h2 class="section-title text-2xl mb-6">4. 与 HashMap 的关系</h2>
                <p class="mb-6"><span class="text-indigo-600">HashSet</span> 是基于 <span class="text-indigo-600">HashMap</span> 实现的，因此它的扩容机制与 <span class="text-indigo-600">HashMap</span> 完全相同。<span class="text-indigo-600">HashSet</span> 内部实际上使用 <span class="text-indigo-600">HashMap</span> 的结构来管理元素：</p>
                <div class="space-y-4">
                    <div class="list-item">
                        <span class="font-medium">键值对:</span> 在 <span class="text-indigo-600">HashSet</span> 中，键是实际存储的元素，值则是一个固定的常量对象（通常是 <span class="font-mono bg-gray-100 px-1 rounded">Boolean.TRUE</span>）。因此，<span class="text-indigo-600">HashSet</span> 扩容的过程实际上是 <span class="text-indigo-600">HashMap</span> 扩容过程的一部分。
                    </div>
                    <div class="list-item">
                        <span class="font-medium">扩容时机:</span> <span class="text-indigo-600">HashSet</span> 的扩容时机和 <span class="text-indigo-600">HashMap</span> 相同，即当 <span class="text-indigo-600">HashMap</span> 的负载因子条件被满足时，会触发扩容。
                    </div>
                </div>
                <div class="mt-8 grid md:grid-cols-2 gap-6">
                    <div>
                        <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1634003158059-cf18507d-dd79-4303-bae1-bbfb09139711.png" alt="HashSet结构图示" class="w-full rounded-lg image-zoom">
                        <p class="text-center text-sm text-gray-500 mt-2">HashSet底层结构示意图</p>
                    </div>
                    <div>
                        <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1634003261590-0a506de0-6002-4f9a-be20-f392ec7fee57.png" alt="HashSet与HashMap关系" class="w-full rounded-lg image-zoom">
                        <p class="text-center text-sm text-gray-500 mt-2">HashSet与HashMap关系图</p>
                    </div>
                </div>
            </div>

            <!-- Visualization Section -->
            <div class="content-card p-8" id="visualization">
                <h2 class="section-title text-2xl mb-6">5. 可视化解析</h2>
                <div class="mermaid">
                    graph LR
                    A[HashSet] -->|基于| B[HashMap]
                    B --> C[数组+链表/红黑树]
                    C --> D[负载因子0.75]
                    D -->|触发条件| E[元素数≥容量×0.75]
                    E --> F[扩容为2倍]
                    F --> G[重新哈希]
                    G --> H[元素迁移]
                </div>
                <div class="mt-6">
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1644807654729-98dd8213-7169-4835-b466-33243f28dd11.png" alt="HashSet源码截图" class="w-full rounded-lg image-zoom">
                </div>
                <div class="mt-6">
                    <p class="font-medium text-gray-700"><span class="text-indigo-600">HashSet</span>特点：无序且不可重复的单值集合。</p>
                </div>
                <div class="mt-6">
                    <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1634003296990-f509020e-54ce-407b-8fa1-af79494c3824.png" alt="HashSet实现原理" class="w-full rounded-lg image-zoom">
                </div>
                <div class="mt-6 bg-indigo-50 p-6 rounded-lg">
                    <h3 class="font-semibold text-lg text-indigo-700 mb-3">核心总结</h3>
                    <p>因为<span class="text-indigo-600">HashSet</span>底层是通过<span class="text-indigo-600">HashMap</span>实现的，所有要研究它的扩容就要去研究<span class="text-indigo-600">HashMap</span>的扩容机制。</p>
                </div>
            </div>
        </div>
    </main>

    <!-- Footer -->
    <footer class="footer py-8">
        <div class="container mx-auto px-6 text-center">
            <div class="flex flex-col items-center">
                <div class="text-lg font-medium mb-2">技术小馆</div>
                <a href="http://www.yuque.com/jtostring" class="text-sm hover:underline">http://www.yuque.com/jtostring</a>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });

        // Image zoom effect
        document.querySelectorAll('.image-zoom').forEach(img => {
            img.addEventListener('click', function() {
                if (this.style.transform === 'scale(1.5)') {
                    this.style.transform = 'scale(1)';
                    this.style.cursor = 'zoom-in';
                } else {
                    this.style.transform = 'scale(1.5)';
                    this.style.cursor = 'zoom-out';
                }
            });
        });
    </script>
</body>
</html>
```